package ch.simplix.android.repetitive.implementation;

import android.content.Context;
import android.os.PowerManager;
import android.util.Log;

public class WakeLockManager {
	// debug tag
	private static String TAG = "WakeLockManager";

	
	public static void setup(Context inCtx) {
		if (instance != null)
			return;
		instance = new WakeLockManager(inCtx);
	}
	

	public static boolean isSetup() {
		return (instance != null) ? true : false;
	}

	public static int s_acquire() {
		assertSetup();
		return instance.acquire();
	}

	public static int s_release() {
		assertSetup();
		return instance.release();
	}

	private static void assertSetup() {
		if (WakeLockManager.instance == null) {
			Log.w(WakeLockManager.TAG, "You need to call setup first");
			throw new RuntimeException("You need to call setup first");
		}
	}

	// *************************************************
	// * A pure private implementation
	// *************************************************

	// Keep count of visitors to know the last visitor.
	// On destory set the count to zero to clear the wake lock
	private int count;

	// Our switch
	PowerManager.WakeLock wl = null;

	/*
	 * Singleton.
	 */
	private WakeLockManager(Context inCtx) {
		wl = this.createWakeLock(inCtx);
	}

	private static WakeLockManager instance = null;

	/*
	 * The methods "acquire" and "release" are expected to be called in tandem.
	 * 
	 * On "acquire" increment the count.
	 * 
	 * This is a synchronized method as multiple threads will be entering and
	 * leaving.
	 */
	synchronized private int acquire() {
		count++;
		Log.d(TAG, "Entering: count=" + count);
		if (count == 1) {
			wl.acquire();
		}
		return count;
	}

	/*
	 * The methods "enter" and "leave" are expected to be called in tandem.
	 * 
	 * On "leave" decrement the count.
	 * 
	 * If the count reaches zero turn off the lights.
	 * 
	 * This is a synchronized method as multiple threads will be entering and
	 * leaving.
	 */
	synchronized private int release() {
		Log.d(TAG, "Leaving: count=" + count);
		// if the count is already zero
		// just leave.
		if (count == 0) {
			Log.w(TAG, "Count is zero.");
			return count;
		}
		count--;
		if (count == 0) {
			// Last visitor
			// release wake lock
			if (this.wl.isHeld()) {
				Log.d(TAG, "Releasing wake lock. No more visitors");
				this.wl.release();
			}
		}
		return count;
	}

	/*
	 * Standard code to create a partial wake lock
	 */
	private PowerManager.WakeLock createWakeLock(Context inCtx) {
		PowerManager pm = (PowerManager) inCtx
				.getSystemService(Context.POWER_SERVICE);

		PowerManager.WakeLock wl = pm.newWakeLock(
				PowerManager.PARTIAL_WAKE_LOCK, TAG);
		return wl;
	}

}
